package com.chaintor.demo.math;

import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math3.exception.DimensionMismatchException;

/**
 * SABR用于牛顿迭代的单变量可微分函数
 * 固定SABR mu、rho,只优化alpha
 */
public class NewtonSolveSABRUnivariateDiffFunc implements UnivariateDifferentiableFunction {
    private SigmaSABRFunction m_SABRFunc;
    private double m_nu;
    private double m_rho;
    private double m_sigemaATM;

    /**
     * 固定SABR mu、rho,只优化alpha
     * @param sabr
     * @param nu
     * @param rho
     * @param sigemaATM
     */
    public NewtonSolveSABRUnivariateDiffFunc(SigmaSABRFunction sabr,double nu,double rho,double sigemaATM){
        this.m_SABRFunc = sabr;
        this.m_nu =nu;
        this.m_rho = rho;
        this.m_sigemaATM = sigemaATM;
    }

    /**
     * 返回函数值和导函数值
     * @param t
     * @return
     * @throws DimensionMismatchException
     */
    public DerivativeStructure value(DerivativeStructure t) throws DimensionMismatchException {
        double x = t.getValue();
        double y = this.value(x);
        double dy = this.dvalue(x);
        return new DerivativeStructure(1,1,y,dy);
    }

    /**
     * 返回函数值
     * @param x
     * @return
     */
    public double value(double x) {
        return m_SABRFunc.value(x,m_rho,m_nu)-m_sigemaATM;
    }

    /**
     * 近似导数值
     * @param x
     * @return
     */
    private double dvalue(double x){
        double y0 = this.value(x+1E-12);
        double y1 = this.value(x-1E-12);
        return (y0-y1)/(2*1E-12);
    }
}
